#include <iostream>
#include <vector>
#include "Thread.hpp"

// using namespace ThreadModule;

#define NUM 4

// 1.锁本身是全局的，那么锁也是共享资源！谁保证锁的安全？？
// pthread_mutex:加锁和解锁被设计成为原子的了
// 2.如何看待锁呢？二元信号量就是锁！
//    2.1 枷锁本质就是对资源展开预订！整体使用资源！！
// 3.如果申请锁的时候，锁被别人拿走了，怎么办？其他线程要进行阻塞等待
// 4.线程在访问临界区代码的时候，可不可以切换？？ 可以切换！！
//    4.1我被切走的时候，别人能进来吗？？不能！我是抱着锁，被切换的！！
//       相当于串行，效率低的原因！原子性！
// 5.如果不遵守这个约定？？bug！
//pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int ticketnum = 10000; // 共享资源，临界资源

class ThreadData
{
public:
    std::string _name;
    pthread_mutex_t *lock_ptr;
};

void Ticket(ThreadData &td)
{
    pthread_mutex_lock(td.lock_ptr); // 枷锁
    while (true)
    {
        if (ticketnum > 0)
        {
            // usleep(1100);

            // 1.抢票
            printf("get a new ticket, who get it: %s, id: %d\n", td._name.c_str(), ticketnum--);

            usleep(1100);
            pthread_mutex_unlock(td.lock_ptr);
        }
        else
        {
            pthread_mutex_unlock(td.lock_ptr);
            break;
        }
    }
}

int main()
{
    pthread_mutex_t lock;
    pthread_mutex_init(&lock, nullptr);

    // 1.构建线程对象
    std::vector<ThreadModulex::Thread<ThreadData>> threads;

    for (int i = 0; i < NUM; i++)
    {
        ThreadData *td = new ThreadData();
        td->lock_ptr = &lock;
        threads.emplace_back(Ticket, *td);
        td->_name = threads.back().Name();
    }

    // 2.启动线程
    for (auto &thread : threads)
    {
        thread.Start();
    }

    // 3.回收线程
    for (auto &thread : threads)
    {
        thread.Join();
    }

    pthread_mutex_destroy(&lock);
    return 0;
}